package org.dfg.corejava.nio;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/*
 * NIO应用1：文件复制
 */
public class FileCopy {
	public static void copy() {
		File sf = new File("C:\\1.txt");
		File tf = new File("C:\\2.txt");
		RandomAccessFile sraf = null;
		RandomAccessFile traf = null;
		try {
			sraf = new RandomAccessFile(sf, "r");
			traf = new RandomAccessFile(tf, "rw");

			FileChannel rfc = sraf.getChannel();
			FileChannel wfc = traf.getChannel();

			ByteBuffer buffer = ByteBuffer.allocate(1024);

			int l = -1;
			while ((l = rfc.read(buffer)) != -1) {
				buffer.flip();
				wfc.write(buffer);
				buffer.clear();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				sraf.close();
				traf.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		copy2();
	}

	/**
	 * 内存映射，可以把一个文件看做一个ButeBuffer <br/>
	 * 读取快，但写入与普通io差不多 <br/>
	 * 写文件必须用RandomAccessFile，且会自动写入硬盘 <br/>
	 * 文件超过1.5-2G可以通过一次map不同部分实现
	 */
	public static void copy2() {
		File file = new File("C:/1.txt");
		try {
			FileInputStream fis = new FileInputStream(file);
			FileChannel fc = fis.getChannel();
			MappedByteBuffer mbb = fc
					.map(FileChannel.MapMode.READ_ONLY, 0, file.length());

			System.out.println(mbb.hasArray());

			// 文件操作

			mbb = null;// 某人在官网上提出的解决该问题的方法
			System.gc();

			fis.close();
			fc.close();
			// 该类有个问题，即，api未提供unmap方法，所以即使流已关闭，该文件依然有可能被占用
			// 只有在垃圾回收是才会清楚map所占用的文件句柄，而gc是随机的
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
